/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pl.tom.social.analyzer.gui.component;

import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JFrame;
import javax.swing.table.TableModel;
import org.apache.log4j.Logger;
import org.openide.util.NbBundle;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
//import org.openide.util.ImageUtilities;
import org.netbeans.api.settings.ConvertAsProperties;
import pl.tom.social.analyzer.cluster.JungCluster;
import pl.tom.social.analyzer.common.CentralityType;
import pl.tom.social.analyzer.common.Results;
import pl.tom.social.analyzer.analysis.CentralityAnalysis;
import pl.tom.social.analyzer.cluster.LingpipeCluster;
import pl.tom.social.analyzer.common.ClusterType;
import pl.tom.social.analyzer.common.MultiClusterType;
import pl.tom.social.analyzer.graph.GraphBuilder;
import pl.tom.social.analyzer.graph.GraphNode;
import pl.tom.social.analyzer.visualizer.AnalysisVisualizer;
import pl.tom.social.common.types.AnalysisType;

/**
 * Top component which displays something.
 */
@ConvertAsProperties(dtd = "-//pl.tom.social.analyzer.gui.component//Graph//EN",
autostore = false)
public final class GraphTopComponent extends TopComponent {

	private static final Logger logger = Logger.getLogger(GraphTopComponent.class);
	private static GraphTopComponent instance;
	private static GraphNode graph = null;
	/** path to the icon used by the component and its open action */
//    static final String ICON_PATH = "SET/PATH/TO/ICON/HERE";
	private static final String PREFERRED_ID = "GraphTopComponent";

	public GraphTopComponent() {
		initComponents();
		setName(NbBundle.getMessage(GraphTopComponent.class, "CTL_GraphTopComponent"));
		setToolTipText(NbBundle.getMessage(GraphTopComponent.class, "HINT_GraphTopComponent"));
//        setIcon(ImageUtilities.loadImage(ICON_PATH, true));
	}

	public GraphTopComponent(GraphBuilder graphBuilder) {
		graph = new GraphNode(graphBuilder);

		//TODO this is here so that graph is visible. fix it.
		JFrame frame = new JFrame();
		frame.getContentPane().add(graph.getViewer());
		frame.pack();

		initComponents();
		setName(NbBundle.getMessage(GraphTopComponent.class, "CTL_GraphTopComponent"));
		setToolTipText(NbBundle.getMessage(GraphTopComponent.class, "HINT_GraphTopComponent"));
//        setIcon(ImageUtilities.loadImage(ICON_PATH, true));

		analysisCentralityComboBox.setModel(new DefaultComboBoxModel(CentralityType.values()));
		analysisClusterComboBox.setModel(new DefaultComboBoxModel(ClusterType.values()));
		analysisMultiClusterComboBox.setModel(new DefaultComboBoxModel(MultiClusterType.values()));
	}

	/** This method is called from within the constructor to
	 * initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is
	 * always regenerated by the Form Editor.
	 */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        graphPanel = new GraphZoomScrollPane(graph.getViewer());
        optionsPanel = new javax.swing.JPanel();
        optionsTooltipCheckBox = new javax.swing.JCheckBox();
        optionsNameCheckBox = new javax.swing.JCheckBox();
        analysisTabbedPane = new javax.swing.JTabbedPane();
        analysisCentralityPanel = new javax.swing.JPanel();
        analysisCentralityComboBox = new javax.swing.JComboBox();
        analysisCentralityStartButton = new javax.swing.JButton();
        analysisClusterPanel = new javax.swing.JPanel();
        analysisClusterComboBox = new javax.swing.JComboBox();
        analysisClusterStartButton = new javax.swing.JButton();
        analysisClusterSpinner = new javax.swing.JSpinner();
        analysisMultiClusterPanel = new javax.swing.JPanel();
        analysisMultiClusterScrollPane = new javax.swing.JScrollPane();
        analysisMultiClusterList = new javax.swing.JList(CentralityType.values());
        analysisMultiClusterStartButton = new javax.swing.JButton();
        analysisMultiClusterSpinner = new javax.swing.JSpinner();
        analysisMultiClusterComboBox = new javax.swing.JComboBox();

        setAutoscrolls(true);

        graphPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.graphPanel.border.title"))); // NOI18N

        optionsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.optionsPanel.border.title"))); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(optionsTooltipCheckBox, org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.optionsTooltipCheckBox.text")); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(optionsNameCheckBox, org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.optionsNameCheckBox.text")); // NOI18N

        javax.swing.GroupLayout optionsPanelLayout = new javax.swing.GroupLayout(optionsPanel);
        optionsPanel.setLayout(optionsPanelLayout);
        optionsPanelLayout.setHorizontalGroup(
            optionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, optionsPanelLayout.createSequentialGroup()
                .addGroup(optionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(optionsNameCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, 196, Short.MAX_VALUE)
                    .addComponent(optionsTooltipCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, 196, Short.MAX_VALUE))
                .addContainerGap())
        );
        optionsPanelLayout.setVerticalGroup(
            optionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(optionsPanelLayout.createSequentialGroup()
                .addComponent(optionsTooltipCheckBox)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(optionsNameCheckBox)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        analysisTabbedPane.setBorder(javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(), org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.analysisTabbedPane.border.title"))); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(analysisCentralityStartButton, org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.analysisCentralityStartButton.text")); // NOI18N
        analysisCentralityStartButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                analysisCentralityStartButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout analysisCentralityPanelLayout = new javax.swing.GroupLayout(analysisCentralityPanel);
        analysisCentralityPanel.setLayout(analysisCentralityPanelLayout);
        analysisCentralityPanelLayout.setHorizontalGroup(
            analysisCentralityPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(analysisCentralityComboBox, 0, 197, Short.MAX_VALUE)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, analysisCentralityPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(analysisCentralityStartButton))
        );
        analysisCentralityPanelLayout.setVerticalGroup(
            analysisCentralityPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(analysisCentralityPanelLayout.createSequentialGroup()
                .addComponent(analysisCentralityComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(analysisCentralityStartButton))
        );

        analysisTabbedPane.addTab(org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.analysisCentralityPanel.TabConstraints.tabTitle"), analysisCentralityPanel); // NOI18N

        org.openide.awt.Mnemonics.setLocalizedText(analysisClusterStartButton, org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.analysisClusterStartButton.text")); // NOI18N
        analysisClusterStartButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                analysisClusterStartButtonActionPerformed(evt);
            }
        });

        analysisClusterSpinner.setModel(new javax.swing.SpinnerNumberModel(Double.valueOf(1.0d), Double.valueOf(0.0d), null, Double.valueOf(1.0d)));

        javax.swing.GroupLayout analysisClusterPanelLayout = new javax.swing.GroupLayout(analysisClusterPanel);
        analysisClusterPanel.setLayout(analysisClusterPanelLayout);
        analysisClusterPanelLayout.setHorizontalGroup(
            analysisClusterPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(analysisClusterComboBox, 0, 197, Short.MAX_VALUE)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, analysisClusterPanelLayout.createSequentialGroup()
                .addComponent(analysisClusterSpinner, javax.swing.GroupLayout.DEFAULT_SIZE, 134, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(analysisClusterStartButton))
        );
        analysisClusterPanelLayout.setVerticalGroup(
            analysisClusterPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(analysisClusterPanelLayout.createSequentialGroup()
                .addComponent(analysisClusterComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(analysisClusterPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(analysisClusterStartButton)
                    .addComponent(analysisClusterSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
        );

        analysisTabbedPane.addTab(org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.analysisClusterPanel.TabConstraints.tabTitle"), analysisClusterPanel); // NOI18N

        analysisMultiClusterScrollPane.setViewportView(analysisMultiClusterList);

        org.openide.awt.Mnemonics.setLocalizedText(analysisMultiClusterStartButton, org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.analysisMultiClusterStartButton.text")); // NOI18N
        analysisMultiClusterStartButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                analysisMultiClusterStartButtonActionPerformed(evt);
            }
        });

        analysisMultiClusterSpinner.setModel(new javax.swing.SpinnerNumberModel(Double.valueOf(1.0d), null, null, Double.valueOf(1.0d)));

        javax.swing.GroupLayout analysisMultiClusterPanelLayout = new javax.swing.GroupLayout(analysisMultiClusterPanel);
        analysisMultiClusterPanel.setLayout(analysisMultiClusterPanelLayout);
        analysisMultiClusterPanelLayout.setHorizontalGroup(
            analysisMultiClusterPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, analysisMultiClusterPanelLayout.createSequentialGroup()
                .addComponent(analysisMultiClusterSpinner, javax.swing.GroupLayout.DEFAULT_SIZE, 134, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(analysisMultiClusterStartButton))
            .addComponent(analysisMultiClusterComboBox, 0, 197, Short.MAX_VALUE)
            .addComponent(analysisMultiClusterScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 197, Short.MAX_VALUE)
        );
        analysisMultiClusterPanelLayout.setVerticalGroup(
            analysisMultiClusterPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, analysisMultiClusterPanelLayout.createSequentialGroup()
                .addComponent(analysisMultiClusterScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 111, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(analysisMultiClusterComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(analysisMultiClusterPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(analysisMultiClusterStartButton)
                    .addComponent(analysisMultiClusterSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
        );

        analysisTabbedPane.addTab(org.openide.util.NbBundle.getMessage(GraphTopComponent.class, "GraphTopComponent.analysisMultiClusterPanel.TabConstraints.tabTitle"), analysisMultiClusterPanel); // NOI18N

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(analysisTabbedPane)
                    .addComponent(optionsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(graphPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 571, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(optionsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(analysisTabbedPane, javax.swing.GroupLayout.PREFERRED_SIZE, 220, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addComponent(graphPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 338, Short.MAX_VALUE))
                .addContainerGap())
        );
    }// </editor-fold>//GEN-END:initComponents

	private void analysisCentralityStartButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_analysisCentralityStartButtonActionPerformed
		CentralityType type = CentralityType.valueOf(analysisCentralityComboBox.getSelectedItem().toString());
		Map<String, Double> result = CentralityAnalysis.getScore(graph, type);
		TableModel model = AnalysisVisualizer.centralityToJTable(result, type);
		Results.show(model, AnalysisType.GraphCentrality);
	}//GEN-LAST:event_analysisCentralityStartButtonActionPerformed

	private void analysisClusterStartButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_analysisClusterStartButtonActionPerformed
		CentralityType centralityType = CentralityType.valueOf(analysisCentralityComboBox.getSelectedItem().toString());
		ClusterType clusterType = ClusterType.valueOf(analysisClusterComboBox.getSelectedItem().toString());

		switch (clusterType) {
			case EdgeBetweenness:
				JungCluster.EdgeBetweenness(graph.getGraph(), ((Double) analysisClusterSpinner.getValue()).intValue());
				break;
			case StructurallyEquivalent:
				JungCluster.StructurallyEquivalent(graph.getGraph());
				break;
			case WeakComponent:
				JungCluster.WeakComponent(graph.getGraph());
				break;
		}
		graph.refresh();
	}//GEN-LAST:event_analysisClusterStartButtonActionPerformed

	private void analysisMultiClusterStartButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_analysisMultiClusterStartButtonActionPerformed
		MultiClusterType clusterType = MultiClusterType.valueOf(analysisMultiClusterComboBox.getSelectedItem().toString());
		Map<String, List<Double>> results = new HashMap<String, List<Double>>();
		for (Object obj : analysisMultiClusterList.getSelectedValues()) {
			CentralityType type = CentralityType.valueOf(obj.toString());
			if (type != null) {
				Map<String, Double> score = CentralityAnalysis.getScore(graph, type);
				for (String key : score.keySet()) {
					if (results.containsKey(key)) {
						results.get(key).add(score.get(key));
					} else {
						List<Double> vals = new ArrayList<Double>();
						vals.add(score.get(key));
						results.put(key, vals);
					}
				}
			}
		}
		LingpipeCluster.cluster(results, clusterType, (Double)analysisMultiClusterSpinner.getValue());
		graph.refresh();
	}//GEN-LAST:event_analysisMultiClusterStartButtonActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JComboBox analysisCentralityComboBox;
    private javax.swing.JPanel analysisCentralityPanel;
    private javax.swing.JButton analysisCentralityStartButton;
    private javax.swing.JComboBox analysisClusterComboBox;
    private javax.swing.JPanel analysisClusterPanel;
    private javax.swing.JSpinner analysisClusterSpinner;
    private javax.swing.JButton analysisClusterStartButton;
    private javax.swing.JComboBox analysisMultiClusterComboBox;
    private javax.swing.JList analysisMultiClusterList;
    private javax.swing.JPanel analysisMultiClusterPanel;
    private javax.swing.JScrollPane analysisMultiClusterScrollPane;
    private javax.swing.JSpinner analysisMultiClusterSpinner;
    private javax.swing.JButton analysisMultiClusterStartButton;
    private javax.swing.JTabbedPane analysisTabbedPane;
    private javax.swing.JPanel graphPanel;
    private javax.swing.JCheckBox optionsNameCheckBox;
    private javax.swing.JPanel optionsPanel;
    private javax.swing.JCheckBox optionsTooltipCheckBox;
    // End of variables declaration//GEN-END:variables

	/**
	 * Gets default instance. Do not use directly: reserved for *.settings files only,
	 * i.e. deserialization routines; otherwise you could get a non-deserialized instance.
	 * To obtain the singleton instance, use {@link #findInstance}.
	 */
	public static synchronized GraphTopComponent getDefault() {
		if (instance == null) {
			instance = new GraphTopComponent();
		}
		return instance;
	}

	/**
	 * Obtain the GraphTopComponent instance. Never call {@link #getDefault} directly!
	 */
	public static synchronized GraphTopComponent findInstance() {
		TopComponent win = WindowManager.getDefault().findTopComponent(PREFERRED_ID);
		if (win == null) {
			Logger.getLogger(GraphTopComponent.class.getName()).warn(
				"Cannot find " + PREFERRED_ID + " component. It will not be located properly in the window system.");
			return getDefault();
		}
		if (win instanceof GraphTopComponent) {
			return (GraphTopComponent) win;
		}
		Logger.getLogger(GraphTopComponent.class.getName()).warn(
			"There seem to be multiple components with the '" + PREFERRED_ID
			+ "' ID. That is a potential source of errors and unexpected behavior.");
		return getDefault();
	}

	@Override
	public int getPersistenceType() {
		return TopComponent.PERSISTENCE_NEVER;
	}

	@Override
	public void componentOpened() {
	}

	@Override
	public void componentClosed() {
	}

	void writeProperties(java.util.Properties p) {
		// better to version settings since initial version as advocated at
		// http://wiki.apidesign.org/wiki/PropertyFiles
		p.setProperty("version", "1.0");
	}

	Object readProperties(java.util.Properties p) {
		GraphTopComponent singleton = GraphTopComponent.getDefault();
		singleton.readPropertiesImpl(p);
		return singleton;
	}

	private void readPropertiesImpl(java.util.Properties p) {
		String version = p.getProperty("version");
	}

	@Override
	protected String preferredID() {
		return PREFERRED_ID;
	}
}
